﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Text;
using System.DirectoryServices;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace Wagner.SharePoint.Utilities
{
	internal static class IISUtilities
	{
		/// <summary>Attempts to recycle current application pool</summary>
		/// <returns>Boolean indicating if application pool was successfully recycled</returns>
		public static bool RecycleCurrentApplicationPool()
		{
			try
			{
				// Application hosted on IIS that supports App Pools, like 6.0 and 7.0
				if (IsApplicationRunningOnAppPool())
				{
					// Get current application pool name
					string appPoolId = GetCurrentApplicationPoolId();

					// Recycle current application pool
					RecycleApplicationPool(appPoolId);
					return true;
				}
				else
					return false;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsApplicationRunningOnAppPool()
		{
			// Application is not hosted on IIS
			if (!AppDomain.CurrentDomain.FriendlyName.StartsWith("/LM/"))
				return false;

			// Application hosted on IIS that doesn't support App Pools, like 5.1
			else if (!DirectoryEntry.Exists("IIS://Localhost/W3SVC/AppPools"))
				return false;

			else
				return true;
		}

		public static string GetCurrentApplicationPoolId()
		{
			string virtualDirPath = AppDomain.CurrentDomain.FriendlyName;
			virtualDirPath = virtualDirPath.Substring(4);
			int index = virtualDirPath.Length + 1;
			index = virtualDirPath.LastIndexOf("-", index - 1, index - 1);
			index = virtualDirPath.LastIndexOf("-", index - 1, index - 1);
			virtualDirPath = "IIS://localhost/" + virtualDirPath.Remove(index);

			DirectoryEntry virtualDirEntry = new DirectoryEntry(virtualDirPath);
			return virtualDirEntry.Properties["AppPoolId"].Value.ToString();
		}

		public static void RecycleApplicationPool(string appPoolId)
		{
			string appPoolPath = "IIS://localhost/W3SVC/AppPools/" + appPoolId;

			DirectoryEntry appPoolEntry = new DirectoryEntry(appPoolPath);
			appPoolEntry.Invoke("Recycle");
		}

		public static StringCollection GetIISVirtualFolders(string strServer)
		{
			StringCollection strColl = null;
			DirectoryEntry obDirEntry = null;
			DirectoryEntries obDirEntList = null;

			try
			{
				obDirEntry = new DirectoryEntry("IIS://" + strServer + "/W3svc/1/Root");
				obDirEntList = obDirEntry.Children;

				// Process each child entry and add the name of virtual folder
				// to string collection.
				strColl = new StringCollection();
				foreach (DirectoryEntry objChildDE in obDirEntList)
				{
					ProcessDEForIISVFolder(objChildDE, strColl);
				}
			}
			catch (Exception ex)
			{
				//Trace.Write(ex.Message);
				return null;
			}
			return strColl;
		}

		public static void ProcessDEForIISVFolder(DirectoryEntry ob, StringCollection strColl)
		{
			try
			{
				// Check if the schema class is IIsWebVirtualDir or not.
				if (0 == String.Compare(ob.SchemaClassName, "IIsWebDirectory"))
				{
					strColl.Add(ob.Name);
				}
			}
			catch (Exception ex)
			{
				//Trace.WriteLine(ex.Message);
			}
		}

		public static bool ListAppPool(string serverName, string adminUsername, string adminPassword, string appPoolName)
		{
			//  metabasePath is of the form "IIS://<servername>/W3SVC/AppPools"
			//  for example "IIS://localhost/W3SVC/AppPools" 
			//  appPoolName is of the form "<name>", for example, "MyAppPool"

			DirectoryEntry appPools = new DirectoryEntry("IIS://" + serverName + "/w3svc/apppools", adminUsername, adminPassword);
			bool status = false;
			foreach (DirectoryEntry AppPool in appPools.Children)
			{
				Console.WriteLine(AppPool.Name);

				if (appPoolName.Equals(AppPool.Name, StringComparison.OrdinalIgnoreCase))
				{
					//AppPool.DeleteTree();
					status = true;
					break;
				}
			}
			appPools = null;
			return status;
		}

		/// <summary> 
		/// Adds a host header value to a specified website.  
		/// </summary> 
		/// <param name="hostHeader">The host header. Must be in the form IP:Port:Hostname </param> 
		/// <param name="websiteID">The ID of the website the host header should be added to </param> 
		public static void AddHostHeader(string serverName, string adminUsername, string adminPassword, string websiteName, string hostHeader)
		{
			string siteID = GetSiteID(serverName, adminUsername, adminPassword, websiteName);
			DirectoryEntry root = new DirectoryEntry("IIS://" + serverName + "/W3SVC/" + siteID, adminUsername, adminPassword);
			PropertyValueCollection serverBindings = root.Properties["ServerBindings"];

			//Add the new binding           
			serverBindings.Add(hostHeader);

			//Create an object array and copy the content to this array           
			Object[] newList = new Object[serverBindings.Count];
			serverBindings.CopyTo(newList, 0);
			//Write to metabase           
			root.Properties["ServerBindings"].Value = newList;
			root.CommitChanges();
			root.Close();
			root.Dispose();
		}

		public static string GetSiteID(string serverName, string adminUsername, string adminPassword, string websiteName)
		{
			DirectoryEntry root = new DirectoryEntry("IIS://" + serverName + "/W3SVC", adminUsername, adminPassword);
			string siteID = "0";

			foreach (DirectoryEntry e in root.Children)
			{
				//if ((e.SchemaClassName == "IIsWebServer")
				//   && (e.Properties["ServerComment"][0].ToString() == websiteName))

				if (e.SchemaClassName == "IIsWebServer")
				{
					if (e.Properties["ServerBindings"].Value.ToString().Contains(":80:"))
					{
						Console.WriteLine();
						Console.WriteLine();
						WriteProperty(e.Properties["ServerComment"]);
						WriteProperty(e.Properties["ServerBindings"]);
						WriteProperty(e.Properties["AppPoolId"]);

						//foreach (string name in e.Properties.PropertyNames)
						//{
						//   Console.WriteLine(name + " : " + e.Properties[name].Value.ToString());
						//}

						siteID = e.Name;
					}
				}
			}

			root.Close();
			root.Dispose();
			return siteID;
		}

		public static void ListIisApplicationPoolProperties(string serverName, string adminUsername, string adminPassword, string appPoolName)
		{
			//  metabasePath is of the form "IIS://<servername>/W3SVC/AppPools"
			//  for example "IIS://localhost/W3SVC/AppPools" 
			//  appPoolName is of the form "<name>", for example, "MyAppPool"
			using (DirectoryEntry appPools = new DirectoryEntry("IIS://" + serverName + "/w3svc/apppools", adminUsername, adminPassword))
			{
				foreach (DirectoryEntry appPool in appPools.Children)
				{
					Console.WriteLine();
					Console.WriteLine();
					Console.WriteLine(appPool.Name);

					if (string.IsNullOrEmpty(appPoolName)
						|| appPoolName.Equals(appPool.Name, StringComparison.OrdinalIgnoreCase))
					{
						WriteProperties(appPool.Properties);
					}
				}
			}
		}

		public static void ListIisWebSiteProperties(string serverName, string adminUsername, string adminPassword)
		{
			using (DirectoryEntry root = new DirectoryEntry("IIS://" + serverName + "/W3SVC", adminUsername, adminPassword))
			{
				foreach (DirectoryEntry e in root.Children)
				{
					if (e.SchemaClassName == "IIsWebServer")
					{
						Console.WriteLine();
						Console.WriteLine();
						Console.WriteLine(e.Properties["ServerComment"][0].ToString());
						WriteProperties(e.Properties);
					}
				}

				root.Close();
			}
		}

		private static void WriteProperties(PropertyCollection properties)
		{
			foreach (PropertyValueCollection property in properties)
				Console.WriteLine(property.PropertyName + " : " + property.Value.ToString());
		}

		private static void WriteProperty(PropertyValueCollection property)
		{
			Console.WriteLine(property.PropertyName + " : " + property.Value.ToString());
		}

		public static SPApplicationPool GetApplicationPool(string url)
		{
			using (SPSite site = new SPSite(url))
			{
				return site.WebApplication.ApplicationPool;
			}
		}
	}
}
